﻿
#include "baseNumber.h"
#include <iostream>
#include "VulkanApplication.h"
#include "SDL2/SDL_vulkan.h"
#include <fstream>
#include "glm/glm.hpp"
#include <array>
#include "SDL2/SDL_ttf.h"
// 并行渲染数
static const int FLATH = 2;
// 当前的帧数
static size_t currentFrameIndex = 0;
//
static const int VERTEX_NUMBER = 3;
struct Point
{
	// 位置信息
	glm::vec2 pos;
	// 颜色
	glm::vec3 color;
	static VkVertexInputBindingDescription getVertexInputBindDesc()
	{
		VkVertexInputBindingDescription bindingDescription{};
		bindingDescription.stride = sizeof(Point);
		bindingDescription.binding = 0;
		bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

		return bindingDescription;
	}
	static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions()
	{
		std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{  };
		// 位置布局
		attributeDescriptions[0].binding = 0;
		attributeDescriptions[0].location = 0;
		attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
		attributeDescriptions[0].offset = offsetof(Point, pos);
		// 位置对应的颜色
		attributeDescriptions[1].binding =0;
		attributeDescriptions[1].location =1;
		attributeDescriptions[1].format =VK_FORMAT_R32G32B32_SFLOAT;
		attributeDescriptions[1].offset =offsetof(Point,color);
		return attributeDescriptions;
	};
};
// 三角型坐标信息
static Point pos[] = {
	{{0.0f, 0.5f},{1,0,0}},
	{{0.0f, 0.0f},{1,1,0}},
	{{0.5f, 0.0f},{1,0,1}},
};
/**
 * 三角形位置坐标
 */

// 文件读取
std::vector<char> readShader(const char *fileName)
{
	std::ifstream shaderFile(fileName, std::ios::ate | std::ios::binary);
	if (!shaderFile.is_open())
	{
		std::cout << "shaderFile open file fail " << std::endl;
		std::vector<char> nullbuf;
		return nullbuf;
	}
	// 返回整个文件大小
	size_t size = shaderFile.tellg();
	std::cout << "shaderFile size is " << size << std::endl;
	shaderFile.seekg(0);
	std::vector<char> buff(size);
	shaderFile.read(buff.data(), size);
	shaderFile.close();
	return buff;
};

// 设置正确的扩展
VkExtent2D choiceSwapExtent2D(const VkSurfaceCapabilitiesKHR &capabilities)
{
	if (capabilities.currentExtent.width != XBWUC_ numberMax())
	{
		return capabilities.currentExtent;
	}
}

XBWUC_ VulkanApplication::VulkanApplication()
{
	initWindow();
	initVulkan();
}

void XBWUC_ VulkanApplication::drawFrame()
{

	// 等待上一帧完成绘制
	vkWaitForFences(vkDevice, 1, &inFlathFences[currentFrameIndex], true, UINT64_MAX);
	vkResetFences(vkDevice, 1, &inFlathFences[currentFrameIndex]);
	uint32_t imageIndex;
	// 从交换链中获取图片
	VkResult result = vkAcquireNextImageKHR(vkDevice, vkSwapchainKHR, UINT64_MAX,
											swapchainSemphores[currentFrameIndex], VK_NULL_HANDLE, &imageIndex);
	// 通过结果判断是否需要重新创建交换链，由于屏幕大小发生改变，获取的图片可能不再适合显示，所以需要重新创建交换链
	if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
	{
		reCreateSwapChain();
		return;
	}
	vkResetCommandBuffer(vkCommandBuffers[currentFrameIndex], 0);
	recordCommandBuffer(vkCommandBuffers[currentFrameIndex], imageIndex);
	VkSubmitInfo submitInfo{};
	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
	// 设置图片获取信号
	VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
	submitInfo.waitSemaphoreCount = 1;
	submitInfo.pWaitSemaphores = &swapchainSemphores[currentFrameIndex];
	submitInfo.pWaitDstStageMask = waitStages;
	// 设置命令缓冲区
	submitInfo.commandBufferCount = 1;
	submitInfo.pCommandBuffers = &vkCommandBuffers[currentFrameIndex];
	// 设置图片渲染完成信号
	submitInfo.pSignalSemaphores = &renderFinSheamphores[currentFrameIndex];
	submitInfo.signalSemaphoreCount = 1;
	// 提交队列
	vkQueueSubmit(graphQueue.queue, 1, &submitInfo, inFlathFences[currentFrameIndex]);
	VkPresentInfoKHR presentInfo{};
	presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
	presentInfo.pWaitSemaphores = &renderFinSheamphores[currentFrameIndex];
	presentInfo.waitSemaphoreCount = 1;
	presentInfo.swapchainCount = 1;
	presentInfo.pSwapchains = &vkSwapchainKHR;
	presentInfo.pImageIndices = &imageIndex;
	result = vkQueuePresentKHR(graphQueue.queue, &presentInfo);
	if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
	{
		reCreateSwapChain();
	}
	// 增长frame no
	currentFrameIndex = (currentFrameIndex + 1) % FLATH;
}
/**
 * 流程主循环
 *
 */
void XBWUC_ VulkanApplication::mainLoop()
{
	SDL_Event event;

	while (true)
	{
		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
			{
				exit(1);
			}
		}
		vkDeviceWaitIdle(vkDevice);
		pos[0].pos[1]+=0.01;
		drawFrame();
		// 延迟30ms
		SDL_Delay(16);
	}
}

// 初始化sdl window
void XBWUC_ VulkanApplication::initWindow()
{
	int code = 0;
	if (code = SDL_Init(SDL_INIT_VIDEO) == 0)
	{
		code = SDL_Vulkan_LoadLibrary(nullptr);
		int result =TTF_Init();
		swindow.window = SDL_CreateWindow("vulkan_demo", SDL_WINDOWPOS_UNDEFINED,
										  SDL_WINDOWPOS_UNDEFINED, DEFAULT_WIDTH, DEFAULT_HEIGHT, (uint32_t)SDL_WINDOW_VULKAN);
	}
	else
	{
		printf("sdl init fail code is %d", code);
		exit(1);
	}
}

// 查询队列
void findQueueFamilies(VkPhysicalDevice &physicalDevice)
{
	uint32_t count = 0;
	vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
	std::vector<VkQueueFamilyProperties> queueFamiliy(count);
	vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, queueFamiliy.data());
}

void XBWUC_ VulkanApplication::choiceGraphCard()
{
	uint32_t count = 0;
	vkEnumeratePhysicalDevices(vkInstance, &count, nullptr);
	if (count == 0)
	{
		std::cout << "no physicalDevice" << std::endl;
		return;
	}
	vkEnumeratePhysicalDevices(vkInstance, &count, &vkPhysicalDevice);
	VkPhysicalDeviceProperties physicalDeviceProperties;
	vkGetPhysicalDeviceProperties(vkPhysicalDevice, &physicalDeviceProperties);
	SDL_Log("device name is %s", physicalDeviceProperties.deviceName);
	VkPhysicalDeviceFeatures physicalDeviceFuture;
	vkGetPhysicalDeviceFeatures(vkPhysicalDevice, &physicalDeviceFuture);
}

void XBWUC_ VulkanApplication::createLogicDevice()
{
	VkDeviceQueueCreateInfo queueCreateInfo{};
	queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
	// 设置队列数量
	vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueCreateInfo.queueCount, nullptr);
	std::vector<VkQueueFamilyProperties> queueFamiliyProperties(queueCreateInfo.queueCount);
	vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueCreateInfo.queueCount, queueFamiliyProperties.data());
	int i = 0;
	queueCreateInfo.queueCount = 1;
	const float queuePriorities = 1.0f;
	queueCreateInfo.pQueuePriorities = &queuePriorities;

	for (auto queue : queueFamiliyProperties)
	{ // 队列属性
		if (queue.queueFlags & VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT)
		{
			queueCreateInfo.queueFamilyIndex = i;
			break;
		}
		i++;
	}

	VkDeviceCreateInfo deviceCreateInfo{};
	deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
	// 设备特性
	VkPhysicalDeviceFeatures deviceFeature{};
	deviceCreateInfo.queueCreateInfoCount = 1;
	deviceCreateInfo.pEnabledFeatures = &deviceFeature;
	// 设置扩展
	uint32_t extensionCount = 0;
	std::vector<char *> extensionName;
	extensionName.push_back((char *)VK_KHR_SWAPCHAIN_EXTENSION_NAME);
	deviceCreateInfo.enabledExtensionCount = extensionName.size();
	deviceCreateInfo.ppEnabledExtensionNames = extensionName.data();
	VkResult result = vkCreateDevice(vkPhysicalDevice, &deviceCreateInfo, nullptr, &vkDevice);
	if (result == VK_SUCCESS)
	{
		vkGetDeviceQueue(vkDevice, i, 0, &graphQueue.queue);
		graphQueue.index = i;
		std::cout << "create device success" << std::endl;
	}
}
void XBWUC_ VulkanApplication::createSwapChain()
{
	VkSwapchainCreateInfoKHR createInfo{};
	createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
	createInfo.surface = vksurface;
	createInfo.minImageCount = swapChainInfo.capability.minImageCount + 1;
	if (createInfo.minImageCount > swapChainInfo.capability.maxImageCount)
	{
		createInfo.minImageCount = swapChainInfo.capability.maxImageCount;
	}

	createInfo.imageFormat = swapChainInfo.surfaceFormat->format;
	createInfo.imageColorSpace = swapChainInfo.surfaceFormat->colorSpace;
	createInfo.imageExtent = choiceSwapExtent2D(swapChainInfo.capability);
	createInfo.imageArrayLayers = 1;
	createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
	// 设置图像队列
	createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
	createInfo.queueFamilyIndexCount = 0;
	createInfo.pQueueFamilyIndices = nullptr;
	createInfo.preTransform = swapChainInfo.capability.currentTransform;
	createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	createInfo.presentMode = swapChainInfo.presentModelKHR;
	createInfo.clipped = VK_TRUE;
	if (vkCreateSwapchainKHR(vkDevice, &createInfo, nullptr, &vkSwapchainKHR) == VK_SUCCESS)
	{
		//
		uint32_t count = 0;
		vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &count, nullptr);
		vkimages.resize(count);
		vkGetSwapchainImagesKHR(vkDevice, vkSwapchainKHR, &count, vkimages.data());
		createImageView();
	}
}
void XBWUC_ VulkanApplication::createImageView()
{
	if (!vkimages.empty())
	{
		vkImageViews.resize(vkimages.size());
		int i = 0;
		for (auto &image : vkimages)
		{
			VkImageViewCreateInfo createInfo{};
			createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
			createInfo.image = image;
			createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
			createInfo.format = swapChainInfo.surfaceFormat->format;
			createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
			createInfo.components.g = createInfo.components.r;
			createInfo.components.b = createInfo.components.r;
			createInfo.components.a = createInfo.components.r;
			createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			createInfo.subresourceRange.baseMipLevel = 0;
			createInfo.subresourceRange.levelCount = 1;
			createInfo.subresourceRange.baseArrayLayer = 0;
			createInfo.subresourceRange.layerCount = 1;
			vkCreateImageView(vkDevice, &createInfo, nullptr, vkImageViews.data() + i);
			i++;
		}
	}
}

void XBWUC_ VulkanApplication::createRenderPass()
{
	VkAttachmentDescription colorAttachment;
	colorAttachment.flags = 0;
	colorAttachment.format = swapChainInfo.surfaceFormat->format;
	colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
	colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
	colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
	colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
	colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
	colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
	colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
	VkAttachmentReference attachmentReference;
	attachmentReference.attachment = 0;
	attachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
	VkSubpassDescription subpass{};
	subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
	subpass.colorAttachmentCount = 1;
	subpass.pColorAttachments = &attachmentReference;
	VkRenderPassCreateInfo renderPassCreate{};
	renderPassCreate.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
	renderPassCreate.attachmentCount = 1;
	renderPassCreate.pAttachments = &colorAttachment;
	renderPassCreate.subpassCount = 1;
	renderPassCreate.pSubpasses = &subpass;
	VkSubpassDependency dependency{};
	dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
	dependency.dstSubpass = 0;
	dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
	dependency.srcAccessMask = 0;
	dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
	dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
	renderPassCreate.pDependencies = &dependency;
	renderPassCreate.dependencyCount = 1;
	if (vkCreateRenderPass(vkDevice, &renderPassCreate, nullptr, &vkRenderPass) == VK_SUCCESS)
	{
		SDL_Log("renderPass create success");
	}
}

VkShaderModule XBWUC_ VulkanApplication::createShaderModule(const std::vector<char> &code)
{
	VkShaderModuleCreateInfo createInfo;
	createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
	createInfo.pNext = nullptr;
	createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
	createInfo.codeSize = code.size();
	VkShaderModule shaderModule;
	vkCreateShaderModule(vkDevice, &createInfo, nullptr, &shaderModule);
	return shaderModule;
}

inline void getVkViewport(XBWUC_ SwapChainCheckInfo &swapChainInfo, VkViewport &viewport)
{
	viewport.x = 0;
	viewport.y = 0;
	viewport.width = swapChainInfo.capability.currentExtent.width;
	viewport.height = swapChainInfo.capability.currentExtent.height;
	viewport.minDepth = 0;
	viewport.maxDepth = 1.0f;
}
inline void getRect2d(XBWUC_ SwapChainCheckInfo &swapChainInfo, VkRect2D &rect2d)
{
	rect2d.extent = swapChainInfo.capability.currentExtent;
	rect2d.offset = {0, 0};
}
void XBWUC_ VulkanApplication::createGraphicsPipeline()
{
	VkShaderModule vertShaderModule = createShaderModule(readShader("../shader/vert.spv"));
	VkShaderModule fragShaderModule = createShaderModule(readShader("../shader/frag.spv"));
	// vert
	VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo{};
	vertShaderStageCreateInfo.module = vertShaderModule;
	vertShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	vertShaderStageCreateInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
	vertShaderStageCreateInfo.pName = "main";
	// frag
	VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo{};
	fragShaderStageCreateInfo.module = fragShaderModule;
	fragShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
	fragShaderStageCreateInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
	fragShaderStageCreateInfo.pName = "main";
	std::vector<VkDynamicState> dynamicStates = {
		VK_DYNAMIC_STATE_VIEWPORT,
		VK_DYNAMIC_STATE_SCISSOR};
	VkPipelineShaderStageCreateInfo shaderStageCreateInfos[] = {vertShaderStageCreateInfo, fragShaderStageCreateInfo};
	VkPipelineDynamicStateCreateInfo dynamicStateCreate{};
	dynamicStateCreate.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
	dynamicStateCreate.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
	dynamicStateCreate.pDynamicStates = dynamicStates.data();

	VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{};
	vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
	std::array<VkVertexInputAttributeDescription, 2> attrDesc = Point::getAttributeDescriptions();
	vertexInputStateCreateInfo.pVertexAttributeDescriptions = attrDesc.data();
	vertexInputStateCreateInfo.vertexAttributeDescriptionCount = attrDesc.size();
	VkVertexInputBindingDescription bindDesc = Point::getVertexInputBindDesc();
	vertexInputStateCreateInfo.pVertexBindingDescriptions = &bindDesc;
	vertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
	VkPipelineInputAssemblyStateCreateInfo inputAssmblyStateCreateInfo{};
	inputAssmblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
	inputAssmblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
	inputAssmblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
	//
	VkViewport viewport;
	getVkViewport(swapChainInfo, viewport);
	VkRect2D rect2d;
	rect2d.extent = swapChainInfo.capability.currentExtent;
	rect2d.offset = {0, 0};
	// 视口配置
	VkPipelineViewportStateCreateInfo viewportStateCreateInfo{};
	viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
	viewportStateCreateInfo.scissorCount = 1;
	viewportStateCreateInfo.viewportCount = 1;
	viewportStateCreateInfo.pViewports = &viewport;
	viewportStateCreateInfo.pScissors = &rect2d;
	// 光栅化配置
	VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo{};
	rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
	rasterizationStateCreateInfo.depthClampEnable = false;
	rasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
	rasterizationStateCreateInfo.lineWidth = 1.0f;
	rasterizationStateCreateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
	rasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
	rasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;
	// 采样配置
	VkPipelineMultisampleStateCreateInfo multiSampleStateCreateInfo{};
	multiSampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
	multiSampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
	multiSampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
	multiSampleStateCreateInfo.minSampleShading = 1.0f;
	multiSampleStateCreateInfo.pSampleMask = nullptr;			 // Optional
	multiSampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE; // Optional
	multiSampleStateCreateInfo.alphaToOneEnable = VK_FALSE;		 // Optional
	// 颜色混合配置
	VkPipelineColorBlendAttachmentState colorBlend{};

	colorBlend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
								VK_COLOR_COMPONENT_G_BIT |
								VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
	colorBlend.blendEnable = VK_FALSE;
	colorBlend.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;  // Optional
	colorBlend.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
	colorBlend.colorBlendOp = VK_BLEND_OP_ADD;			   // Optional
	colorBlend.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;  // Optional
	colorBlend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
	colorBlend.alphaBlendOp = VK_BLEND_OP_ADD;			   // Optional
	VkPipelineColorBlendStateCreateInfo colorBlendCreateInfo{};
	colorBlendCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
	colorBlendCreateInfo.logicOpEnable = VK_FALSE;
	colorBlendCreateInfo.logicOp = VK_LOGIC_OP_COPY; // Optional
	colorBlendCreateInfo.attachmentCount = 1;
	colorBlendCreateInfo.pAttachments = &colorBlend;
	colorBlendCreateInfo.blendConstants[0] = 0.0f; // Optional
	colorBlendCreateInfo.blendConstants[1] = 0.0f; // Optional
	colorBlendCreateInfo.blendConstants[2] = 0.0f; // Optional
	colorBlendCreateInfo.blendConstants[3] = 0.0f; // Optional
	VkPipelineLayoutCreateInfo pipelineLayoutCreate{};
	memset(&pipelineLayout, 0, sizeof(&pipelineLayout));
	pipelineLayoutCreate.pNext = nullptr;
	pipelineLayoutCreate.flags = 0;
	pipelineLayoutCreate.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
	pipelineLayoutCreate.setLayoutCount = 0;		 // Optional
	pipelineLayoutCreate.pSetLayouts = nullptr;		 // Optional
	pipelineLayoutCreate.pushConstantRangeCount = 0; // Optional
	pipelineLayoutCreate.pPushConstantRanges = nullptr;
	vkCreatePipelineLayout(vkDevice, &pipelineLayoutCreate, nullptr, &pipelineLayout);
	// create renderPipline
	VkGraphicsPipelineCreateInfo createInfo{};
	createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
	createInfo.stageCount = 2;
	createInfo.pNext = nullptr;
	createInfo.pStages = shaderStageCreateInfos;
	createInfo.pVertexInputState = &vertexInputStateCreateInfo;
	createInfo.pColorBlendState = &colorBlendCreateInfo;
	createInfo.pDynamicState = &dynamicStateCreate;
	createInfo.pMultisampleState = &multiSampleStateCreateInfo;
	createInfo.pRasterizationState = &rasterizationStateCreateInfo;
	createInfo.pDepthStencilState = nullptr;
	createInfo.pInputAssemblyState = &inputAssmblyStateCreateInfo;
	createInfo.pViewportState = &viewportStateCreateInfo;
	createInfo.layout = pipelineLayout;
	createInfo.renderPass = vkRenderPass;
	createInfo.subpass = 0;
	// createInfo.basePipelineHandle;
	createInfo.basePipelineIndex = -1;
	// 创建渲染管线
	VkResult result = vkCreateGraphicsPipelines(vkDevice, 0, 1, &createInfo, nullptr, &vkPipeline);
	if (result != VK_SUCCESS)
	{
	}
	vkDestroyShaderModule(vkDevice, vertShaderModule, nullptr);
	vkDestroyShaderModule(vkDevice, fragShaderModule, nullptr);
}

// 找到适合的类型
uint32_t XBWUC_ VulkanApplication::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
	VkPhysicalDeviceMemoryProperties physicalDeviceProperties;
	vkGetPhysicalDeviceMemoryProperties(vkPhysicalDevice,&physicalDeviceProperties);
	int a= 3& 5;
	for (uint32_t i = 0; i < physicalDeviceProperties.memoryTypeCount; i++)
	{
		if (typeFilter & (1 << i) &&
		   (physicalDeviceProperties.memoryTypes[i].propertyFlags & properties) ==properties)
		{
			return i;
		}
	}
}
// 创建顶点缓冲区
void XBWUC_ VulkanApplication::createVertexBuffer()
{
	VkBufferCreateInfo createInfo{};
	createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
	createInfo.size = sizeof(Point) * VERTEX_NUMBER;
	// 指定buffer 用途
	createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
	// 是否共享
	createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
	vkCreateBuffer(vkDevice, &createInfo, nullptr, &vertexBuffer);
	VkMemoryRequirements memoryRequire;
	vkGetBufferMemoryRequirements(vkDevice, vertexBuffer, &memoryRequire);
	// 创建内存分配
	VkMemoryAllocateInfo memAllocateInfo{};
	memAllocateInfo.sType =VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
	memAllocateInfo.allocationSize =memoryRequire.size;
	memAllocateInfo.memoryTypeIndex =findMemoryType(memoryRequire.memoryTypeBits,
	   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
	//内存分配
	VkResult result = vkAllocateMemory(vkDevice,&memAllocateInfo,nullptr,&deviceMemory);
	if(result== VK_SUCCESS){
		vkBindBufferMemory(vkDevice,vertexBuffer,deviceMemory,0);
	}
	// 内存映射
	void * data;
	vkMapMemory(vkDevice,deviceMemory,0,createInfo.size,0,&data);
	memcpy(data,pos,createInfo.size);
	vkUnmapMemory(vkDevice,deviceMemory);
}

void XBWUC_ VulkanApplication::createFrameBuffer()
{
	framebuffers.resize(vkImageViews.size());
	// 循环创建
	for (int i = 0; i < vkImageViews.size(); i++)
	{
		VkFramebufferCreateInfo createInfo{};
		createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
		createInfo.renderPass = vkRenderPass;
		createInfo.attachmentCount = 1;
		createInfo.pAttachments = vkImageViews.data() + i;
		createInfo.width = swapChainInfo.capability.currentExtent.width;
		createInfo.height = swapChainInfo.capability.currentExtent.height;
		createInfo.layers = 1;
		vkCreateFramebuffer(vkDevice, &createInfo, nullptr, framebuffers.data() + i);
	}
}

void XBWUC_ VulkanApplication::recordCommandBuffer(VkCommandBuffer &commandBuffer, uint32_t &imageIndex)
{
	int result =0;
	VkCommandBufferBeginInfo beginInfo{};
	beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
	beginInfo.flags = 0;
	vkBeginCommandBuffer(commandBuffer, &beginInfo);
	VkRenderPassBeginInfo renderPassBegin{};
	renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
	renderPassBegin.renderPass = vkRenderPass;
	renderPassBegin.framebuffer = framebuffers.data()[imageIndex];
	renderPassBegin.renderArea.offset = {0, 0};
	renderPassBegin.renderArea.extent = swapChainInfo.capability.currentExtent;
	VkClearValue vkCleanValue = {{0.1f, 0, 0}};
	renderPassBegin.clearValueCount = 1;
	renderPassBegin.pClearValues = &vkCleanValue;
	vkCmdBeginRenderPass(commandBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
	vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline);
	VkBuffer buffers[] = {vertexBuffer};
	VkDeviceSize deviceSize[] ={0};
	vkCmdBindVertexBuffers(commandBuffer,0,1,buffers,deviceSize);
	VkViewport vkViewport;
	getVkViewport(swapChainInfo, vkViewport);
	vkCmdSetViewport(commandBuffer, 0, 1, &vkViewport);
	VkRect2D rect;
	getRect2d(swapChainInfo, rect);
	vkCmdSetScissor(commandBuffer, 0, 1, &rect);
	vkCmdDraw(commandBuffer, 3, 1, 0, 0);
	vkCmdEndRenderPass(commandBuffer);
	result =vkEndCommandBuffer(commandBuffer);
	if (result !=VkResult::VK_SUCCESS)
	{
		std::cout << "end commandBuffer fail" << result <<std::endl;
	}
	
}
void XBWUC_ VulkanApplication::createCommandPool()
{
	VkCommandPoolCreateInfo createInfo{};
	createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
	createInfo.queueFamilyIndex = graphQueue.index;
	VkResult result = vkCreateCommandPool(vkDevice, &createInfo, nullptr, &vkCommandPool);
	if (result == VK_SUCCESS)
	{
		createCommandBuffer();
	}
}
void XBWUC_ VulkanApplication::createCommandBuffer()
{
	VkCommandBufferAllocateInfo allocate{};
	vkCommandBuffers.resize(FLATH);
	allocate.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
	allocate.commandPool = vkCommandPool;
	allocate.commandBufferCount = FLATH;
	allocate.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
	vkAllocateCommandBuffers(vkDevice, &allocate, vkCommandBuffers.data());
}
XBWUC_ VulkanApplication::~VulkanApplication()
{
	freeResource();
}

/**
 * 销毁vulkan资源
 *
 */
void XBWUC_ VulkanApplication::freeResource()
{
	if (swindow.window)
	{
		// 资源销毁
		SDL_DestroyRenderer(swindow.render);
		SDL_DestroyWindow(swindow.window);
	}
	vkDestroySurfaceKHR(vkInstance, vksurface, nullptr);
	// 资源释放
	vkDestroyInstance(vkInstance, nullptr);
	vkDestroyRenderPass(vkDevice, vkRenderPass, nullptr);
	vkDestroyPipeline(vkDevice, vkPipeline, nullptr);
	vkDestroyPipelineLayout(vkDevice, pipelineLayout, nullptr);
	cleanupSwapChain();
	vkDestroyBuffer(vkDevice, vertexBuffer, nullptr);
	vkFreeMemory(vkDevice,deviceMemory,nullptr);
	// 销毁同步对象
	for (int i = 0; i < FLATH; i++)
	{
		vkDestroySemaphore(vkDevice, renderFinSheamphores[i], nullptr);
		vkDestroySemaphore(vkDevice, swapchainSemphores[i], nullptr);
		vkDestroyFence(vkDevice, inFlathFences[i], nullptr);
	}

	vkDestroyDevice(vkDevice, nullptr);
}
/*
 * 获取验证层名称
 */
void getValidationLayer(VkInstanceCreateInfo &createInfo)
{
	vkEnumerateInstanceLayerProperties(&createInfo.enabledLayerCount, nullptr);
	std::vector<VkLayerProperties> layerProperties(createInfo.enabledLayerCount);
	vkEnumerateInstanceLayerProperties(&createInfo.enabledLayerCount, layerProperties.data());
	if (createInfo.enabledLayerCount == 0)
	{ // 没有验证层则直接返回
		return;
	}
	char **names = new char *[createInfo.enabledLayerCount];
	createInfo.ppEnabledLayerNames = names;
	for (uint32_t i = 0; i < createInfo.enabledLayerCount; i++)
	{
		char *name = new char[VK_MAX_EXTENSION_NAME_SIZE];
		names[i] = name;
		memcpy(names[i], layerProperties.data()[i].layerName, VK_MAX_EXTENSION_NAME_SIZE);
	}
}

/**
 * 创建surface，目前由sdl托管，所以不需要担心平台问题。
 */
void XBWUC_ VulkanApplication::createsurface()
{
	SDL_bool result = SDL_Vulkan_CreateSurface(swindow.window, vkInstance, &vksurface);
	if (result)
	{
		vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkPhysicalDevice, vksurface, &swapChainInfo.capability);
		choiceSwapExtent2D(swapChainInfo.capability);
		uint32_t count = 0;
		vkGetPhysicalDeviceSurfaceFormatsKHR(vkPhysicalDevice, vksurface, &count, nullptr);
		if (count != 0)
		{
			std::vector<VkSurfaceFormatKHR> surfaceFormats(count);
			vkGetPhysicalDeviceSurfaceFormatsKHR(vkPhysicalDevice, vksurface, &count,
												 surfaceFormats.data());
			// 选择合适的surfaceFormat
			swapChainInfo.choiceRightSurfaceFormatKHR(surfaceFormats);
		}
		count = 0;
		// 获取显示模式
		vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vksurface,
												  &count, nullptr);
		if (count != 0)
		{
			std::vector<VkPresentModeKHR> models(count);
			vkGetPhysicalDeviceSurfacePresentModesKHR(vkPhysicalDevice, vksurface,
													  &count, models.data());
			// 选择合适的
			swapChainInfo.choiceRightPersentModeKHR(models);
		}
	}
	else
	{
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_GetError());
		exit(1);
	}
}

void XBWUC_ VulkanApplication::createSyncObject()
{

	VkSemaphoreCreateInfo semaphoreInfo{};
	semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
	VkFenceCreateInfo fenceInfo{};
	fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
	// 创建fence就将状态置为signaled ,否则在绘制第一帧时将会一直阻塞。
	fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
	renderFinSheamphores.resize(FLATH);
	swapchainSemphores.resize(FLATH);
	inFlathFences.resize(FLATH);
	for (int i = 0; i < FLATH; i++)
	{
		vkCreateSemaphore(vkDevice, &semaphoreInfo, nullptr, renderFinSheamphores.data() + i);
		vkCreateSemaphore(vkDevice, &semaphoreInfo, nullptr, swapchainSemphores.data() + i);
		vkCreateFence(vkDevice, &fenceInfo, nullptr, inFlathFences.data() + i);
	}
}

void XBWUC_ VulkanApplication::cleanupSwapChain()
{

	for (auto frameBuffer : framebuffers)
	{
		vkDestroyFramebuffer(vkDevice, frameBuffer, nullptr);
	}
	// 销毁图像视图
	if (!vkImageViews.empty())
	{
		for (auto &imageView : vkImageViews)
		{
			vkDestroyImageView(vkDevice, imageView, nullptr);
		}
	}
	// 销毁交换链
	if (vkSwapchainKHR)
	{
		vkDestroySwapchainKHR(vkDevice, vkSwapchainKHR, nullptr);
	}
}
void XBWUC_ VulkanApplication::reCreateSwapChain()
{
	vkDeviceWaitIdle(vkDevice);
	cleanupSwapChain();
	createSwapChain();
	createImageView();
	createFrameBuffer();
}
/**
 * 创建vulkan 实例。
 * @param window sdl 窗口
 * @param vkInstance 需要创建的vkInstance
 */
inline VkResult createInstance(SDL_Window *window, VkInstance &vkInstance)
{
	VkApplicationInfo vkApplicationInfo{};
	vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
	vkApplicationInfo.pApplicationName = "vulkanLearn";
	vkApplicationInfo.pEngineName = "hello";
	vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
	vkApplicationInfo.engineVersion = vkApplicationInfo.applicationVersion;
	vkApplicationInfo.apiVersion = VK_API_VERSION_1_0;
	VkInstanceCreateInfo createInfo{};
	createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
	createInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
	createInfo.pApplicationInfo = &vkApplicationInfo;
	uint32_t extensCount = 0;
	// getValidationLayer(createInfo);
	std::vector<char *> extensionNames;

	SDL_ClearError();
	// 获取扩展数量
	SDL_bool issuccess = SDL_Vulkan_GetInstanceExtensions(window,
														  &extensCount,
														  nullptr);
	if (!issuccess)
	{

		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_GetError());
		SDL_ClearError();
		exit(1);
	}
	// 存在扩展时才获取名字。
	if (extensCount > 0)
	{
		extensionNames.resize( extensCount);
		SDL_Vulkan_GetInstanceExtensions(window,
										 &extensCount,
										 (const char **)extensionNames.data());
	}
	// 解决mac_os 驱动不兼容的问题错误为：VK_ERROR_INCOMPATIBLE_DRIVER
	extensionNames.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
	createInfo.ppEnabledExtensionNames = extensionNames.data();
	createInfo.enabledExtensionCount = extensionNames.size();
	return vkCreateInstance(&createInfo, nullptr, &vkInstance);
}
void XBWUC_ VulkanApplication::initVulkan()
{

	VkResult result = createInstance(swindow.window, vkInstance);
	// 释放验证层名称
	if (result == VK_SUCCESS)
	{
		std::cout << "createInstance successd  " << std::endl;
		choiceGraphCard();
		createLogicDevice();
		createsurface();
		createSwapChain();
		createRenderPass();
		createGraphicsPipeline();
		createVertexBuffer();
		createFrameBuffer();
		createCommandPool();
		createSyncObject();
	}else{
		std::cout<< "create instance fail,result is "<<result <<std::endl;
		exit(1);
	}
}
